//////////////////////////////////////////////////////////////////////////
///	\file:	AutoHelper.h
///	Copyright (MingYou) 2009 - All Rights Reserved
///	Author:	Robert.Ma
///	Date:	[2009/04/25]
///	Description:
///		Implement a template-class for auto free object or not free object.
//////////////////////////////////////////////////////////////////////////
#pragma once

template<class T>
class CFreeObject
{
public:
    CFreeObject() : m_pPointer(NULL), m_bAutoFree(TRUE)
    {}

    CFreeObject(T* pPointer, BOOL bAutoFree = TRUE)
            : m_pPointer(pPointer), m_bAutoFree(bAutoFree)
    {}

    ~CFreeObject()
    {
        if ( m_bAutoFree )
        {
            delete m_pPointer;
        }
    }

    T* Get()
    {
        return m_pPointer;
    }

    operator T*()
    {
        return m_pPointer;
    }

    void operator = (T* p)
    {
        if ( m_bAutoFree )
        {
            delete m_pPointer;
        }

        m_pPointer = p;
    }

private:
    T*		m_pPointer;
    BOOL	m_bAutoFree;
};

template<class T>
class CFreeGDIObject
{
public:
    CFreeGDIObject() : m_hObject(NULL), m_bAutoFree(TRUE)
    {}

    CFreeGDIObject(T hObj, BOOL bAutoFree = TRUE)
            : m_hObject(hObj), m_bAutoFree(bAutoFree)
    {}

    ~CFreeGDIObject()
    {
        FreeObject();
    }

    T Get()
    {
        return m_hObject;
    }

    operator T()
    {
        return m_hObject;
    }

    CFreeGDIObject& operator =(T t)
    {
        Set(t);

        return *this;
    }

    void Set(T t, BOOL bAutoFree = TRUE)
    {
        FreeObject();

        m_hObject	= t;
        m_bAutoFree	= bAutoFree;
    }

private:
    void FreeObject()
    {
        if ( m_bAutoFree )
        {
            ::DeleteObject(m_hObject);
        }
    }

    T		m_hObject;
    BOOL	m_bAutoFree;
};

typedef CFreeGDIObject<HBITMAP>	CAutoBitmap;
typedef CFreeGDIObject<HBRUSH>	CAutoBrush;
typedef CFreeGDIObject<HPEN>	CAutoPen;

class CAutoCursor
{
public:
    CAutoCursor(HCURSOR hSetCur)
    {
        m_hOldCur = ::SetCursor(hSetCur);
    }

    CAutoCursor(HINSTANCE hInstance, LPCWSTR lpCursorName)
    {
        HCURSOR hSetCur = ::LoadCursor(hInstance, lpCursorName);

        m_hOldCur = ::SetCursor(hSetCur);
    }

    ~CAutoCursor()
    {
        ::SetCursor(m_hOldCur);
    }

private:
    CAutoCursor();

    HCURSOR m_hOldCur;
};

class CAutoDisableWindow
{
public:
    CAutoDisableWindow(HWND hWnd, BOOL bSetFocus = TRUE)
            : m_hWnd(hWnd),
            m_bSetFocus(bSetFocus)
    {
        ::EnableWindow(hWnd, FALSE);
    }

    ~CAutoDisableWindow()
    {
        ::EnableWindow(m_hWnd, TRUE);

        if ( m_bSetFocus )
        {
            ::SetFocus(m_hWnd);
        }
    }


private:
    HWND    m_hWnd;
    BOOL    m_bSetFocus;
};

class CAutoCompatibleDC
{
public:
    CAutoCompatibleDC(HDC hDC)
    {
        m_hDC = ::CreateCompatibleDC(hDC);
    }

    ~CAutoCompatibleDC()
    {
        ::DeleteDC(m_hDC);
    }

    operator HDC()
    {
        return m_hDC;
    };

    HDC Get()
    {
        return m_hDC;
    };

private:
    CAutoCompatibleDC()
    {}

    HDC m_hDC;
};

class CAutoClientDC
{
public:
    CAutoClientDC(HWND hWnd)
            : m_hWnd(hWnd)
    {
        m_hDC = ::GetDC(hWnd);
    }

    ~CAutoClientDC()
    {
        ::ReleaseDC(m_hWnd, m_hDC);
    }

    operator HDC()
    {
        return m_hDC;
    };

    HDC Get()
    {
        return m_hDC;
    };

private:
    CAutoClientDC()
    {}

    HWND	m_hWnd;
    HDC		m_hDC;
};
